﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Com.Binaria.SISCOB.DTO;
using Com.Binaria.SISCOB.Dom;
using Com.Binaria.SISCOB.Funcional.DTO;
using Com.Binaria.Core.Enumeracion;
using Com.Binaria.Core.Attribute;
using System.Transactions;
using Com.Binaria.Core.Exceptions;
using Com.Binaria.Core;
using System.Diagnostics;
using Com.Binaria.Core.Util;

namespace Com.Binaria.SISCOB.Mgr
{
    public class CargaArchivoMgr: ICargaArchivoMgr
    {
        public ICartolaDom iCartolaDom;
        public ICartolaMayorDom iCartolaMayorDom;
        public ICuentaCorrienteDom iCuentaCorrienteDom;
        public IItemCartolaDom iItemCartolaDom;
        public ISucursalDom iSucursalDom;
        public IRegistroContableDom iRegistroContableDom;
        public IEgresoDom iEgresoDom;
        public IIngresoDom iIngresoDom;
        public IDocumentoTransaccionDom iDocumentoTransaccionDom;
        public IConstante iConstante;

        [TrasanctionAttribute(TransactionScopeOption.Required)]
        public string ImportarArchivo(string ruta,String tipo)
        {
            List<ItemCartolaDTO> itemsCartola = null;
            List<RegistroContableDTO> registrosContables = null;
            List<DocumentoTransaccionDTO> docsTrans = null;
            Dictionary<string,RegistroContableDTO> dicRC = new Dictionary<string,RegistroContableDTO>();
            List<CartolaDTO> listCartolaResultDTO = null;
            List<CartolaMayorDTO> listCartolaMayorResultDTO = null;

            long tot = 0;
            StringBuilder logResult = new StringBuilder();

            DirectoryInfo dir = new DirectoryInfo(ruta);

            if (dir.Exists)
            {
                FileInfo[] files = dir.GetFiles();
                foreach (FileInfo file in files)
                {
                    try
                    {

                        logResult.Append(string.Format("Procesando Archivo : {0}", file.Name));
                        if (tipo.Equals("C"))
                        {
                            itemsCartola = PrepararItemCartola(file);

                            listCartolaResultDTO = iCartolaDom.BuscarCartolaFiltro(new ContextoDTO(), new CartolaDTO() { Folio = itemsCartola[0].Cartola.Folio, IdCuentaCorriente = itemsCartola[0].Cartola.IdCuentaCorriente, FchEmision = itemsCartola[0].Cartola.FchEmision });
                            if (listCartolaResultDTO.Count == 0)
                            {
                                itemsCartola = RegistrarItemsCartola(itemsCartola);

                                docsTrans = PrepararDocumentoTransaccion(itemsCartola);

                            }
                            else
                            {
                                throw new ManagerException(Factoria.GetMessage("MGR_CARTOLA_EXIST"), TraceEventType.Warning);
                            }
                        }
                        if (tipo.Equals("M"))
                        {
                            dicRC = new Dictionary<string, RegistroContableDTO>();
                            registrosContables = PrepararRegistrosContable(file);

                            listCartolaMayorResultDTO = iCartolaMayorDom.BuscarCartolaMayorFiltro(new ContextoDTO(), new CartolaMayorDTO() { FchDesde = registrosContables[0].CartolaMayor.FchDesde, IdCuentaCorriente = registrosContables[0].CartolaMayor.IdCuentaCorriente });
                            if (listCartolaMayorResultDTO.Count == 0)
                            {

                                foreach (RegistroContableDTO rc in registrosContables)
                                {
                                    string clave = String.Concat(rc.FchRegistro, rc.Monto, rc.NmrDcto, rc.NmrAsiento);
                                    if (dicRC.ContainsKey(clave))
                                    {
                                        RegistroContableDTO rcTmp = dicRC[clave];
                                        rcTmp.Monto += rc.Monto;
                                        tot += (long)rc.Monto;
                                    }
                                    else
                                    {
                                        dicRC.Add(clave, rc);
                                        tot += (long)rc.Monto;
                                    }
                                }

                                logResult.Append(" Monto: " + tot);
                                registrosContables = dicRC.Values.ToList();


                                registrosContables = RegistrarRegistrosContable(registrosContables);

                                docsTrans = PrepararDocumentoTransaccion(registrosContables);
                            }
                            else
                            {
                                throw new ManagerException(Factoria.GetMessage("MGR_CARTOLA_EXIST"), TraceEventType.Warning);
                            }
                        }
                        logResult.Append(" Resultado: Ok..!");
                        logResult.Append("\n");
                        logResult.Append("\n");
                        file.Delete();
                    }
                    catch (ManagerException me)
                    {
                        logResult.Append(" Resultado: " + me.Message);
                        logResult.Append("\n");
                        logResult.Append("\n");
                    }
                }
            }

            return logResult.ToString();
        }



        private List<ItemCartolaDTO> PrepararItemCartola(FileInfo file)
        {
            CuentaCorrienteDTO ctaCteDTO = null;
            CartolaDTO cartolaDTO = null;
            ItemCartolaDTO itemCartolaDTO = null;
            SucursalDTO sucursalDTO = null;

            List<ItemCartolaDTO> itemsCartola = new List<ItemCartolaDTO>();

            StreamReader sr = null;
            int nmrFila = 1;
            int totTra = 0;
            int linTra = 1;
            long totalMonto = 0;

            //FileInfo arch = new FileInfo(pathfilename);

            if (file.Exists)
            {
                sr = file.OpenText();

                while (!sr.EndOfStream)
                {
                    String[] strFila = sr.ReadLine().Split(';');

                    if (nmrFila < 19)
                    {
                        switch (nmrFila)
                        {
                            case 7:
                                ctaCteDTO = new CuentaCorrienteDTO();
                                ctaCteDTO.NmrCuenta = strFila[0].Substring(0, (strFila[0].Length -1));
                                ctaCteDTO.EstaActivo = true;
                                break;
                            case 10:
                                cartolaDTO = new CartolaDTO();
                                cartolaDTO.Usuario = strFila[0].Substring(0, (strFila[0].Length -1));
                                cartolaDTO.FchEmision = parseDate(strFila[2],'-');
                                break;
                            case 13:
                                cartolaDTO.CuentaCorriente = ctaCteDTO;
                                cartolaDTO.Folio = Convert.ToInt32(strFila[0].Substring(0, strFila[0].Length-1));
                                cartolaDTO.FchDesde = parseDate(strFila[3],'-');
                                cartolaDTO.FchHasta = parseDate(strFila[4],'-');
                                totTra = Convert.ToInt32(strFila[1].Substring(0, strFila[1].Length - 1));
                                break;

                                
                        }
                    }
                    else
                    {
                        //if (linTra <= totTra)
                        if (strFila[1].Trim().Length > 0 && strFila[3].Trim().Length > 0)
                        {
                            itemCartolaDTO = new ItemCartolaDTO();
                            sucursalDTO = new SucursalDTO();

                            sucursalDTO.Descripcion = strFila[1].Substring(0, strFila[1].Length - 1);
                            sucursalDTO.EstaActivo = true;

                            itemCartolaDTO.Cartola = cartolaDTO;
                            itemCartolaDTO.Sucursal = sucursalDTO;
                            if (strFila[2].Length > 0)
                            {
                                itemCartolaDTO.NmrOperacion = strFila[2].Substring(0, strFila[2].Length - 1);

                            }
                            itemCartolaDTO.DscOperacion = strFila[3].Substring(0, strFila[3].Length - 1).ToUpper();
                            // Tipo de ItemContable por defecto
                            itemCartolaDTO.Tipo = "C";
                            if (strFila[5].Length > 0)
                            {
                                itemCartolaDTO.Monto = parseMonto(strFila[5]);
                                itemCartolaDTO.NmrOperacion = "00000";
                                itemCartolaDTO.Tipo = "A";

                            }
                            if (strFila[4].Length > 0)
                            {
                                itemCartolaDTO.Monto = parseMonto(strFila[4]);
                                itemCartolaDTO.Tipo = "C";
                            }

                            itemCartolaDTO.Monto = (itemCartolaDTO.Monto == null ? 0 : itemCartolaDTO.Monto);

                            itemCartolaDTO.FchOperacion = parseDate(strFila[0].Substring(0, strFila[0].Length - 1) + "/" + cartolaDTO.FchDesde.Value.Year.ToString(), '-');
                            itemCartolaDTO.EstaProcesado = false;


                            totalMonto += (long)itemCartolaDTO.Monto;

                            linTra++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    nmrFila++;

                    if (itemCartolaDTO != null)
                    {
                        itemsCartola.Add(itemCartolaDTO);
                        itemCartolaDTO = null;
                    }
                }
            }
            sr.Close();
            Console.WriteLine("Monto Importado: " + totalMonto);

            return itemsCartola;
        }


        private List<DocumentoTransaccionDTO> PrepararDocumentoTransaccion(List<ItemCartolaDTO> itemsCartola)
        {
            List<DocumentoTransaccionDTO> listDocTransResult = new List<DocumentoTransaccionDTO>();
            DocumentoTransaccionDTO dctoTransDTO = null;
            EgresoDTO egresoDTO = null;
            IngresoDTO ingresoDTO = null;

            long tot = 0;

            foreach (ItemCartolaDTO ic in itemsCartola)
            {
                if (ic.Tipo.Equals("C"))
                {
                    // Se crea DocumentoTransaccion (Egreso)
                    egresoDTO = new EgresoDTO();
                    dctoTransDTO = new DocumentoTransaccionDTO();

                    egresoDTO.EsManual = false;
                    egresoDTO.Estado = "ON";

                    dctoTransDTO.IdCuentaCorriente = ic.Cartola.IdCuentaCorriente;
                    dctoTransDTO.IdSucursal = ic.IdSucursal;
                    dctoTransDTO.Monto = ic.Monto;
                    dctoTransDTO.FchDocumento = ic.FchOperacion;
                    dctoTransDTO.FchUpdate = DateTime.Now;
                    dctoTransDTO.Glosa = ic.DscOperacion;
                    dctoTransDTO.NmrDocumento = ic.NmrOperacion;
                    dctoTransDTO.UserName = iConstante.getValue("UsrSystem");
                    dctoTransDTO.Egreso = egresoDTO;
                    dctoTransDTO.EstaActivo = true;

                }

                if (ic.Tipo.Equals("A"))
                {
                    // Se crea DocumentoTransaccion (Ingreso)
                    ingresoDTO = new IngresoDTO();
                    dctoTransDTO = new DocumentoTransaccionDTO();

                    ingresoDTO.Tipo = "SN";
                    ingresoDTO.Estado = "OB";

                    dctoTransDTO.IdCuentaCorriente = ic.Cartola.IdCuentaCorriente;
                    dctoTransDTO.IdSucursal = ic.IdSucursal;
                    dctoTransDTO.Monto = ic.Monto;
                    dctoTransDTO.FchDocumento = ic.FchOperacion;
                    dctoTransDTO.FchUpdate = DateTime.Now;
                    dctoTransDTO.Glosa = ic.DscOperacion;
                    dctoTransDTO.NmrDocumento = ic.NmrOperacion;
                    dctoTransDTO.UserName = iConstante.getValue("UsrSystem");
                    dctoTransDTO.Ingreso = ingresoDTO;
                    dctoTransDTO.EstaActivo = true;

                }

                tot += dctoTransDTO.Monto.Value;

                listDocTransResult.Add(dctoTransDTO);

            }

            Console.WriteLine(string.Format("Monto Dcto.Transaccional : {0}", tot.ToString()));
            listDocTransResult = RegistrarDocumentoTransaccion(listDocTransResult);

            return listDocTransResult;
        }

        private List<DocumentoTransaccionDTO> PrepararDocumentoTransaccion(List<RegistroContableDTO> registrosContable)
        {
            Dictionary<string,DocumentoTransaccionDTO> dicDocTransResult = new Dictionary<string,DocumentoTransaccionDTO>();
            List<DocumentoTransaccionDTO> listDocTransResult = new List<DocumentoTransaccionDTO>();
            List<RegistroContableDTO> listRegContableResultDTO = null;
            DocumentoTransaccionDTO dctoTransDTO = null;
            EgresoDTO egresoDTO = null;
            IngresoDTO ingresoDTO = null;

            long tot = 0;
            long total = 0;
            String clave = string.Empty;


            foreach (RegistroContableDTO rc in registrosContable)
            {
                tot = 0;

                if (rc.Tipo.Equals("E"))
                {
                    listRegContableResultDTO = iRegistroContableDom.BuscarRegistroContableByEgreso(new ContextoDTO(), rc);


                    listRegContableResultDTO.ForEach(r => tot += (long)r.Monto);
                    clave = string.Concat(rc.CartolaMayor.IdCuentaCorriente + ";" + rc.NmrDcto);



                    // Se crea DocumentoTransaccion (Egreso)
                    egresoDTO = new EgresoDTO();
                    dctoTransDTO = new DocumentoTransaccionDTO();

                    egresoDTO.EsManual = false;
                    egresoDTO.Estado = "GI";  // Egreso Girado

                    dctoTransDTO.IdCuentaCorriente = rc.CartolaMayor.IdCuentaCorriente;
                    dctoTransDTO.Monto = tot;
                    dctoTransDTO.FchDocumento = rc.FchRegistro;
                    dctoTransDTO.FchUpdate = DateTime.Now;
                    dctoTransDTO.Glosa = rc.Glosa;
                    dctoTransDTO.NmrDocumento = rc.NmrDcto;
                    dctoTransDTO.UserName = iConstante.getValue("UsrSystem");
                    dctoTransDTO.Egreso = egresoDTO;
                    dctoTransDTO.EstaActivo = true;

                }

                if (rc.Tipo.Equals("I"))
                {
                    listRegContableResultDTO = iRegistroContableDom.BuscarRegistroContableByIngreso(new ContextoDTO(), rc);
                    listRegContableResultDTO.ForEach(r => tot += (long)r.Monto);
                    clave = string.Concat(rc.CartolaMayor.IdCuentaCorriente + ";" + rc.FchRegistro+";"+rc.Monto);

                    // Se crea DocumentoTransaccion (Ingreso)
                    ingresoDTO = new IngresoDTO();
                    dctoTransDTO = new DocumentoTransaccionDTO();

                    ingresoDTO.Tipo = "SN";  
                    ingresoDTO.Estado = "RE";  // Ingreso Registrado

                    dctoTransDTO.IdCuentaCorriente = rc.CartolaMayor.IdCuentaCorriente;
                    dctoTransDTO.Monto = tot;
                    dctoTransDTO.FchDocumento = rc.FchRegistro;
                    dctoTransDTO.FchUpdate = DateTime.Now;
                    dctoTransDTO.Glosa = rc.Glosa;
                    dctoTransDTO.NmrDocumento = rc.NmrDcto;
                    dctoTransDTO.UserName = iConstante.getValue("UsrSystem");
                    dctoTransDTO.Ingreso = ingresoDTO;
                    dctoTransDTO.EstaActivo = true;

                }


                if (!dicDocTransResult.Keys.Contains(clave))
                {
                    if (dctoTransDTO.Monto != 0)
                    {
                        dicDocTransResult.Add(clave, dctoTransDTO);
                        total += tot;
                    }
                }

            }

            Console.WriteLine(string.Format("Total *** : {0} de ({1})", total,dicDocTransResult.Count));

            listDocTransResult = RegistrarDocumentoTransaccion(dicDocTransResult.Values.ToList());

            return listDocTransResult;
        }


        private List<RegistroContableDTO> PrepararRegistrosContable(FileInfo file)
        {
            RegistroContableDTO regConDTO = null;
            CartolaMayorDTO cartolaMayorDTO = null;
            CuentaCorrienteDTO ctaCteDTO = null;

            List<RegistroContableDTO> registrosContable = new List<RegistroContableDTO>();

            StreamReader sr = null;
            int nmrFila = 1;
            long totalMonto = 0;
            StringBuilder fechaEmi = new StringBuilder();

            //FileInfo arch = new FileInfo(pathfilename);

            if (file.Exists)
            {
                sr = file.OpenText();

                while (!sr.EndOfStream)
                {
                    String[] strFila = sr.ReadLine().Split(';');

                    if (nmrFila < 13)
                    {
                        switch (nmrFila)
                        {
                            case 1:
                                fechaEmi.Append(strFila[11].Substring(7));
                                fechaEmi.Append(" ");
                                break;
                            case 2:
                                cartolaMayorDTO = new CartolaMayorDTO();
                                fechaEmi.Append(strFila[11].Substring(6));
                                cartolaMayorDTO.FchEmision = parseDate(fechaEmi.ToString(), ' ');
                                break;
                            case 9:
                                ctaCteDTO = new CuentaCorrienteDTO();
                                ctaCteDTO.NmrCuenta = formatCtaCte(strFila[0].Substring(16, 15).Trim());
                                ctaCteDTO.Descripcion = strFila[0].Substring(37).Trim();
                                ctaCteDTO.EstaActivo = true;
                                cartolaMayorDTO.CuentaCorriente = ctaCteDTO;
                                break;
                            case 11:
                                cartolaMayorDTO.FchDesde = parseDate(strFila[0].Substring(7,10), ' ');
                                cartolaMayorDTO.FchHasta = parseDate(strFila[0].Substring(24, 10), ' ');
                                break;
                        }
                    }
                    else
                    {
                        regConDTO = new RegistroContableDTO();
                        regConDTO.CartolaMayor = cartolaMayorDTO;
                        regConDTO.FchRegistro = parseDate(strFila[0],' ');
                        regConDTO.Glosa = string.Concat("(", strFila[7].ToUpper(), ") ", strFila[6].ToUpper());
                        regConDTO.NmrAsiento = strFila[2];
                        regConDTO.NmrDcto = strFila[5];
                        regConDTO.EstaProcesado = false;
                        if (parseMonto(strFila[10]) != 0)
                        {
                            regConDTO.Monto = parseMonto(strFila[10]);
                            regConDTO.Tipo = "I";
                        }
                        if (parseMonto(strFila[11]) != 0)
                        {
                            regConDTO.Monto = parseMonto(strFila[11]);
                            regConDTO.Tipo = "E";
                        }
                        totalMonto += (long)regConDTO.Monto;

                    }
                    nmrFila++;

                    if (regConDTO != null)
                    {
                        registrosContable.Add(regConDTO);
                        regConDTO = null;
                    }
                }
            }
            
            sr.Close();
            Console.WriteLine("Monto Importado: " + totalMonto);
            
            return registrosContable;
        }



        private List<DocumentoTransaccionDTO> RegistrarDocumentoTransaccion(List<DocumentoTransaccionDTO> docsTrans)
        {
            List<DocumentoTransaccionDTO> docsTransResult = null;
            EgresoDTO egresoDTO = null;
            IngresoDTO ingresoDTO = null;
            long tot = 0;

            foreach (DocumentoTransaccionDTO docDTO in docsTrans)
            {
                docsTransResult = new List<DocumentoTransaccionDTO>();

                if (docDTO.Egreso != null)
                {
                    egresoDTO = iEgresoDom.ProbarRegistrar(new ContextoDTO(), docDTO);
                    docDTO.Egreso = egresoDTO;
                }

                if (docDTO.Ingreso != null)
                {
                    ingresoDTO = iIngresoDom.ProbarRegistrar(new ContextoDTO(), docDTO);
                    docDTO.Ingreso = ingresoDTO;
                }


                docsTransResult.Add(docDTO);
                tot += (long)docDTO.Monto;
            }

            Console.WriteLine("Monto .. :" + tot);

            return docsTransResult;
        }


        private List<ItemCartolaDTO> RegistrarItemsCartola(List<ItemCartolaDTO> itemsCartola)
        {
            List<ItemCartolaDTO> itemsCartolaResult = new List<ItemCartolaDTO>();
            long tot = 0;

            foreach (ItemCartolaDTO itemDTO in itemsCartola)
            {
                itemDTO.Cartola.CuentaCorriente = iCuentaCorrienteDom.ProbarRegistrar(new ContextoDTO(), itemDTO.Cartola.CuentaCorriente);
                itemDTO.Cartola.IdCuentaCorriente = itemDTO.Cartola.CuentaCorriente.Id;

                itemDTO.Cartola = iCartolaDom.ProbarRegistrar(new ContextoDTO(), itemDTO.Cartola);
                itemDTO.IdCartola = itemDTO.Cartola.Id;

                itemDTO.Sucursal = iSucursalDom.ProbarRegistrar(new ContextoDTO(), itemDTO.Sucursal);
                itemDTO.IdSucursal = itemDTO.Sucursal.Id;

                itemsCartolaResult.Add(iItemCartolaDom.ProbarRegistrar(new ContextoDTO(), itemDTO));
                tot += itemDTO.Monto.Value;
            }

            Console.WriteLine(string.Format("Monto registrado : {0}" , tot.ToString()));

            return itemsCartolaResult;
        }


        private List<RegistroContableDTO> RegistrarRegistrosContable(List<RegistroContableDTO> registrosContables)
        {
            List<RegistroContableDTO> registrosContablesResult = new List<RegistroContableDTO>();

            foreach (RegistroContableDTO regContDTO in registrosContables)
            {
                regContDTO.CartolaMayor.CuentaCorriente = iCuentaCorrienteDom.ProbarRegistrar(new ContextoDTO(), regContDTO.CartolaMayor.CuentaCorriente);
                regContDTO.CartolaMayor.IdCuentaCorriente = regContDTO.CartolaMayor.CuentaCorriente.Id;

                regContDTO.CartolaMayor = iCartolaMayorDom.ProbarRegistrar(new ContextoDTO(), regContDTO.CartolaMayor);
                regContDTO.IdCartolaMayor = regContDTO.CartolaMayor.Id;


                registrosContablesResult.Add(iRegistroContableDom.ProbarRegistrar(new ContextoDTO(), regContDTO));
            }


            return registrosContablesResult;
        }

        private DateTime? parseDate(String str,char sepa)
        {
            String[] strFchHrs = str.Split(sepa);
            String strFecha = null;
            String strHora = null;
            DateTime? dateResult = null;

            if (strFchHrs != null && strFchHrs.Length > 0)
            {
                strFecha = strFchHrs[0].Substring(0,10);
                if (strFchHrs.Length > 1)
                {
                    strHora = strFchHrs[1].Substring((sepa == '-' ? 1 : 0), 5);
                }
                dateResult = Convert.ToDateTime(strFecha + " " + strHora);
            }

            return dateResult;

            //Convert.ToDateTime(strFila[2].Split('-')[0].Substring(0, (strFila[2].Split('-')[0].Length - 1)) + " " + strFila[2].Split('-')[1].Substring(1, (strFila[2].Split('-')[1].Length - 1)));
        }

        private long parseMonto(String str)
        {
            long montoResult = 0;
            StringBuilder strb = new StringBuilder();
  
            foreach (Char c in str.ToCharArray())
            {
                if (c != '.')
                {
                    strb.Append(c);
                }
            }

            montoResult = Convert.ToInt64(strb.ToString());

            return montoResult;
        }

        private string formatCtaCte(String cta)
        {
            string ctaResult = "";
            StringBuilder ff = new StringBuilder("000-0-000000-0");
            StringBuilder strb = new StringBuilder();

            for (int i = 0; i < (11-cta.Length);i++ )
            {
                strb.Append("0");
            }
            strb.Append(cta);
            int j = 10;
            for (int i = ff.Length-1; i >= 0;i-- )
            {
                if (ff[i].Equals('0'))
                {
                    
                    ff[i] = strb[j--];
                }
            }


            ctaResult = ff.ToString();

            return ctaResult;
        }

    }
}
